home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Shareware Gold
/
Windows Shareware Gold Volume 3 Number 1 (Sherburne Knowledge Systems) (1991).iso
/
utils
/
f3106
/
crdprt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-01
|
13KB
|
313 lines
/*
* crdprt.c - version 2.1 - November 1st, 1990
*
* crdprint - print a Microsoft Windows cardfile
*
* This program will print a cardfile in a simple fashion on any ASCII
* printer. It does not bother drawing the cute (and timeconsuming) boxes
* around the cards.
*
* Art Zemon July 12, 1986
*
* CompuServe: 72406,3275
* UUCP: ucbvax!trwrb!felix!zemon
**************************************************************************
*
* Updated: Munjal M. July 21, 1990
* CompuServe: 76264,602
**************************************************************************
*
* Updated : Version 2.0 - September 5, 1990
* : Rod Hutson... CompuServe 72411,564
* (403) 461-2431 (Edmonton, Alberta, Canada)
* Changes : couldn't get large cardfiles (90 cards, 19000+ bytes) to print
* so changed design of program to use only one file handle and
* track file position with a long variable instead... original
* version used two file handles open simulataneously to maintain
* file position.
* : altered variable names to follow Windows-style Hungarian
* notation (with some variations due mainly to old habits)
* : added copious commenting for those who like such things
* : ensured worked with WINDOWS 3.0 Cardfile files
**************************************************************************
*
* Updated : Version 2.1 - November 1st, 1990
* : Rod Hutson... CompuServe 72411,564
* (403) 461-2431 (Edmonton, Alberta, Canada)
* Changes : modified program to properly handle cardfile cards
* containing graphic images; any card containing a standard
* cardfile 'picture' graphic as well as standard text is
* processed as if the graphic weren't there; if the card
* contains only a graphic image or is blank, only the index
* line is processed; if the card contains text only, then
* it is processed normally;
* : while modifying previous ver 2.0 for the above functionality,
* I discovered a mistake in the card data structures... these
* are now corrected as described below.
* : tested the resulting executable with cardfiles issued by
* WUGNET, consisting of 100,000+ bytes, over 300 cards, and
* many or most with some graphic image(s) on them
* NOTE : rather than obsfucate the code to make it 'nice and tight',
* I have left it loose and readable, and maybe even somewhat
* unstructured (ie. no sub-function calls, etc).
**************************************************************************
*/
#include <stdio.h> /* provides NULL, SEEK_SET, etc */
#include <stdlib.h>
#define TEXT_BUF 512 /* size of text buffer for card text */
#define INDEX_TEXT 40 /* max length of index line string */
#define BYTE char /* a convenience, thats all */
#ifndef NULL /* lint told me NULL not declared, */
#define NULL 0 /* so I did this, just to be sure */
#endif
/**********************************************************/
/* layout the data structures for a MicroSoft '.crd' file */
/**********************************************************/
/* file header structure */
typedef struct {
char acSigniture[3]; /* 3 bytes ... 'MGC' */
int iNumCrds; /* 2 bytes ... number of cards in cardfile */
} sFILEHDR; /* structure is 5 bytes long */
/* index data structure for each card */
typedef struct {
int aiFuture[3]; /* 6 bytes ... reserved for future */
long lOffset; /* 4 bytes ... card offset into file */
BYTE bFlag; /* 1 byte ... some kind of flag */
char acIndexText[INDEX_TEXT]; /* INDEX_TEXT bytes ... index line */
BYTE bNull; /* 1 byte ... always '0' or NULL */
} sINDEXHDR; /* structure is (12+INDEX_TEXT) bytes long */
/* if card contains text only, this structure applies to card data */
typedef struct {
int iLenBMap; /* 2 bytes ... if no bitmap, always 0X0000 */
int iLenText; /* 2 bytes ... number of bytes in text strings */
} sTEXTONLY; /* structure is 4 bytes long */
void main (int argc, char **argv)
{
/* we'll substitute this simple string for the graphics in Windows */
static char acSep[] = "════════════════════════════════════════";
FILE *hFile; /* handle to current cardfile */
sFILEHDR sFileHdr; /* file header variable */
sINDEXHDR sIndexHdr; /* card index line variable */
sTEXTONLY sTextOnly; /* text-only card body variable */
unsigned char acText[TEXT_BUF]; /* card body text buffer */
unsigned int iCard, /* current card count */
iCardFile, /* current cardfile count */
iCheck, /* dummy error variable */
iTextLength; /* dummy text length variable */
long lCurrPos, /* current file position */
lTmpPos; /* dummy file position variable */
/* if command line did not include cardfile(s) to print out, msg & exit */
if (argc < 2) {
fputs ("CrdPrt V2.1, November 1st, 1990\n\n", stderr);
fputs ("Usage: CrdPrt {card-file} [{card-file-2}...]\n", stderr);
fputs ("\t{card-file} is any DOS file-spec including wild-cards.\n\n", stderr);
fputs ("\tCrdPrt will display one or several cardfile(s) in a simple format\n", stderr);
fputs ("\t without wasting valuable time doing fancy graphics.\n", stderr);
exit (1);
}
/* do this until no more cardfile files to process */
iCardFile = 0;
while (++iCardFile < argc) {
/* if cannot open cardfile, msg & exit */
if ((hFile = fopen (argv[iCardFile], "r")) == NULL) {
perror (argv[iCardFile]);
exit (1);
}
fclose (hFile);
/* reopen the file for 'read-binary' access */
hFile = fopen (argv[iCardFile], "rb");
/* read current cardfile file header into appropriate structure */
iCheck = fread ((void *) &sFileHdr, sizeof (sFILEHDR), 1, hFile);
/* if we read incorrect number of records, msg & exit */
if (iCheck != 1) {
perror ("Error reading file header");
fclose (hFile);
exit (1);
}
/* initialize current position in file to origin */
lCurrPos = ftell (hFile);
/* for current cardfile, go thru each card & display/print text */
for (iCard = 1; iCard <= sFileHdr.iNumCrds; ++iCard) {
/* go to file offset of previous card index info */
fseek (hFile, lCurrPos, SEEK_SET);
/* get current index line data */
iCheck = fread (&sIndexHdr, sizeof (sINDEXHDR), 1, hFile);
/* if we read incorrect number of records, msg & exit */
if (iCheck != 1) {
perror ("Error reading cardfile index text");
fclose (hFile);
exit (1);
}
/* note current file position for later */
lCurrPos = ftell (hFile);
/* go to file offset where this card is located */
iCheck = fseek (hFile, sIndexHdr.lOffset, SEEK_SET);
/* if fseek() did not return a 0, msg & exit */
if (iCheck) {
perror ("Error seeking card location in file");
fclose (hFile);
exit (1);
}
/* note start of this card for later */
lTmpPos = ftell (hFile);
/* assuming current card is text only, read first four bytes */
iCheck = fread ((void *) &sTextOnly, sizeof (sTEXTONLY), 1, hFile);
/********************** debugging stuff ************************/
/* ******* uncomment if you want to see progress details *******/
/*
fprintf (stderr, "iCard=%x iCheck=%x iLenBMap=%x iLenText=%x\n",
iCard, iCheck, sTextOnly.iLenBMap,
sTextOnly.iLenText);
getchar ();
*/
/***************************************************************/
/* if we read incorrect number of records, msg & exit */
if (iCheck != 1) {
perror ("Error reading first card body data bytes");
fclose (hFile);
exit (1);
}
/* if first two bytes are 0, then no bitmap */
if (sTextOnly.iLenBMap == 0) {
/* could still be a pure text-bearing card, so check */
if (sTextOnly.iLenText != 0) {
/* okay, there IS some card body text, so process it */
if (sTextOnly.iLenText < TEXT_BUF) {
/* read designated number of card body text chars */
iCheck = fread (acText, 1, sTextOnly.iLenText, hFile);
/* if read incorrect number of chars, msg & exit */
if (iCheck != sTextOnly.iLenText) {
perror ("Error reading card body text");
fclose (hFile);
exit (1);
}
/* write separate string to output */
puts (acSep);
/* write index line to output */
puts (sIndexHdr.acIndexText);
/* write card body text to output */
fwrite (acText, 1, sTextOnly.iLenText, stdout);
putchar ('\n');
}
else
/* uh, oh... more than TEXT_BUF chars in card text */
fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
}
}
else {
/* card contains bitmap of length sTextOnly.iLenBMap bytes */
/* skip graphic by moving to end of bitmap data for this card */
iCheck = fseek (hFile,
(lTmpPos + (long) (10 + sTextOnly.iLenBMap)),
SEEK_SET);
/* if fseek() failed, msg & exit */
if (iCheck) {
perror ("Error moving to end of card bitmap data");
fclose (hFile);
exit (1);
}
/* back to card body text: read length of card text in bytes */
iCheck = fread ((void *) &iTextLength, sizeof (int), 1, hFile);
/************ debugging stuff ***************/
/***** uncomment to see progress details ****/
/*
fprintf (stderr, "iCheck=%x iTextLength=%x\n",
iCheck, iTextLength);
getchar ();
*/
/********************************************/
/* if we had a problem reading text length, msg & exit */
if (iCheck != 1) {
perror ("Error reading in card body text length");
fclose (hFile);
exit (1);
}
/* check to see how many chars are in card body text */
if (iTextLength != 0) {
/* not a blank card, so do your stuff! */
if (iTextLength < TEXT_BUF) {
/* read designated number of card body text bytes */
iCheck = fread (acText, 1, iTextLength, hFile);
/* if read incorrect number of bytes, msg & exit */
if (iCheck != iTextLength) {
perror ("Error reading card body text");
fclose (hFile);
exit (1);
}
/* write separator string to output */
puts (acSep);
/* write index line to output */
puts (sIndexHdr.acIndexText);
/* write card body text to output */
fwrite (acText, 1, iTextLength, stdout);
putchar ('\n');
}
else
/* card body text > TEXT_BUF chars in length */
fputs ("**Error** Cardfile Text Too Long!\a\n", stderr);
}
}
}
/* write final separator string to output, & close current cardfile */
puts (acSep);
fclose (hFile);
}
/* we're outa here! */
exit (0);
}